package io.github.talelin.sleeve.common.utills;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.github.talelin.sleeve.common.exception.FileResolveException;
import io.github.talelin.sleeve.mapper.FileTestMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 解析文件
 */
@Data
@Slf4j
@Component
public class ExcelVerifier extends AnalysisEventListener<Map<String, String>> {

    @Resource
    private FileTestMapper fileTestMapper;

    public ExcelVerifier() {
        super();
    }

    /**
     * 每隔1000条存储数据库，然后清理list，方便内存回收
     */
    private int columnNum = 0;
    private String tableName = "";
    private Map<Integer, String> indexType = new HashedMap(); //存放表第一行的字段
    private long start = 0;
    private long end = 0;

    private int checkFlag = 0;
    private String fileName = "";
    private Long dataNum = 0L; // 数据的行数
    private Long successNum = 0L;
    private Long failureNum = 0L;
    private List<JSONObject> failDataList = new ArrayList<>();
    private List<String> fieldCheck = new ArrayList<>(); //头部 属性

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        start = System.currentTimeMillis();
        log.debug("解析到一条头数据:{}", JSON.toJSONString(headMap));

        fieldCheck.clear();
        indexType.clear();

        tableName = this.fileName.replace(".xlsx", "");
        fieldCheck = fileTestMapper.getTableField(tableName);
        if (fieldCheck == null) {
            throw new FileResolveException("文件名错误");
        }
        columnNum = headMap.size();
        for (int i = 0; i < columnNum; i++) {
            String typeName = headMap.get(i);
            if (!fieldCheck.contains(typeName)) {
                throw new FileResolveException("文件内字段错误，请下载标准文件格式");
            }
            indexType.put(i, typeName);
        }
        dataNum = 0L;
        successNum = 0L;
        failureNum = 0L;
        failDataList.clear();
    }

    @Override
    public void invoke(Map<String, String> data, AnalysisContext context) {
        int rowNum = context.readRowHolder().getRowIndex();
        log.debug("解析到第{}行的一条数据：{}", rowNum, JSON.toJSONString(data));
        dataNum++;
        JSONObject entityData = new JSONObject(true);
        List<String> message = new ArrayList<>();
        for (int i = 0; i < columnNum; i++) {
            String value = data.get(i);
            if (StringUtils.isBlank(value)) {
                value = "";
                message.add(indexType.get(i) + "不可为空");
            }
            entityData.put(indexType.get(i), value);
            if (i == columnNum - 1 && message.size() > 0) {
                entityData.put("failureReason", message);
                failDataList.add(entityData);
            }
        }

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        end = System.currentTimeMillis();
        log.info("Excel文件校验完成,耗时:{}", end - start);
        failureNum = (long) failDataList.size();
        successNum = dataNum - failureNum;
        log.info("校验Excel文件:"+fileName+",成功"+successNum+"条，失败"+failureNum+"条");
        if(successNum.equals(dataNum) && failureNum==0){
            checkFlag = 1;
        }else{
            checkFlag = 0;
        }
        log.info("文件校验结果为：{}",checkFlag);
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
        log.debug("解析失败，但是继续解析下一行：{}", exception.getMessage());
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
            log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
        if(exception instanceof FileResolveException) {
            throw new FileResolveException(exception.getMessage());
        }
    }


}
